﻿using System;
using System.Collections.Generic;
using System.Linq;
using OperationPlugins.ExtensionMethods;

namespace OperationPlugins.Validators
{
    public abstract class AbstractValidator : ContextualPlugin, IValidator
    {
        private readonly IList<string> _messages = new List<string>();
        private SimpleRuleChecker _passChecker;
        private SimpleRuleChecker _failChecker;

        /// <summary>
        /// Gets the validation level.
        /// </summary>
        protected virtual ValidationLevel ValidationLevel
        {
            get { return GetType().GetAttribute<ValidatorOfAttribute>().ValidationLevel; }
        }

        /// <summary>
        /// Gets the simple rule validator.
        /// </summary>
        protected virtual SimpleRuleChecker PassIf
        {
            get { return _passChecker ?? (_passChecker = new SimpleRuleChecker(_messages, true)); }
        }

        /// <summary>
        /// Gets the simple rule validator.
        /// </summary>
        protected virtual SimpleRuleChecker RaiseIf
        {
            get { return _failChecker ?? (_failChecker = new SimpleRuleChecker(_messages, false)); }
        }

        /// <summary>
        /// Gets the current validation result.
        /// </summary>
        protected virtual ValidationResultMessageContainer ValidationResult
        {
            get
            {
                ValidationResultMessageContainer container;

                lock (_messages)
                {
                    if (_messages.Any())
                    {
                        container = new ValidationResultMessageContainer();
                        foreach (string message in _messages)
                        {
                            container.Add(new ValidationResultMessage(ValidationLevel, message));
                        }
                    }
                    else
                    {
                        container = ValidationResultMessageContainer.Success;
                    }
                }

                return container;
            }
        }

        /// <summary>
        /// Performs the validation.
        /// </summary>
        protected abstract void Validate();

        /// <summary>
        /// Validates an object.
        /// </summary>
        /// <param name="value">The object to be validated.</param>
        /// <param name="context">The operation context.</param>
        /// <returns>An instance of the <see cref="ValidationResultMessageContainer"/> class.</returns>
        ValidationResultMessageContainer IValidator.Validate(object value, OperationContext context)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            Value = value;

            Context = context;

            Validate();

            return ValidationResult;
        }

        protected virtual void PassIfTrue(bool condition, string message, params object[] parameters)
        {
            PassIf.True(condition, message, parameters);
        }

        protected virtual void RaiseIfTrue(bool condition, string message, params object[] parameters)
        {
            RaiseIf.True(condition, message, parameters);
        }

        protected virtual void Raise(string message, params object[] parameters)
        {
            RaiseIf.True(true, message, parameters);
        }

    }
}